﻿
using UnityEngine;
using UnityEditor;
using System.IO;
using Jinndev;
using System.Text;
using System.Collections.Generic;
using System.Linq;

namespace JinndevEditor {

    public class CoreAssetsMenu : Editor {

        [MenuItem(CommonEditorConst.AssetsMenu + "/生成缩略图", false)]
        public static void CreateThumbnail() {
            GameObject obj = Selection.activeGameObject;
            if (obj != null) {
                RuntimePreviewGenerator.MarkTextureNonReadable = false;
                RuntimePreviewGenerator.OrthographicMode = false;
                //RuntimePreviewGenerator.PreviewRenderCamera = null;
                RuntimePreviewGenerator.PreviewRenderCamera = Camera.main;
                //RuntimePreviewGenerator.PreviewDirection = new Vector3(-2.543f, -1.950f, 4.440f);
                RuntimePreviewGenerator.PreviewDirection = new Vector3(-1.000f, -0.430f, -0.600f);
                RuntimePreviewGenerator.FieldOfView = 30;
                RuntimePreviewGenerator.BackgroundColor = new Color(49f / 255f, 49f / 255f, 49f / 255f, 0);

                GameObject light = GameObject.Find("Directional Light");
                Quaternion lightRotation = Quaternion.identity;
                if (light != null) {
                    lightRotation = light.transform.rotation;
                    //light.transform.rotation = Quaternion.Euler(130, -200, 0);
                    light.transform.rotation = Quaternion.Euler(135, 65, 0);
                }

                Texture2D texture = RuntimePreviewGenerator.GenerateModelPreview(obj.transform, 256, 256);

                if (light != null) {
                    light.transform.rotation = lightRotation;
                }

                string assetPath = AssetDatabase.GetAssetPath(obj);
                string dir = Path.GetDirectoryName(assetPath);
                string fileName = Path.GetFileNameWithoutExtension(assetPath);
                string imagePath = Path.Combine(dir, fileName + "_Icon.png");

                CommonEditorUtil.SaveTexture(texture, imagePath);

                DestroyImmediate(texture);

                TextureImporter importer = AssetImporter.GetAtPath(imagePath) as TextureImporter;
                importer.mipmapEnabled = false;
                importer.SaveAndReimport();

                Selection.activeObject = AssetDatabase.LoadAssetAtPath<Object>(imagePath);
            }
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/生成缩略图", true)]
        public static bool CreateThumbnailValidation() {
            GameObject obj = Selection.activeGameObject;
            return obj != null;
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/生成为灰度图", false)]
        public static void ConvertToGrayTexture() {
            Texture2D texture = Selection.activeObject as Texture2D;
            bool isReadable = CommonEditorUtil.SetReadable(texture, true);

            Texture2D output = new Texture2D(texture.width, texture.height);
            CommonUtil.ToGray(texture, output, 2);
            output.Apply();

            CommonEditorUtil.SetReadable(texture, isReadable);

            string dir = Path.GetDirectoryName(AssetDatabase.GetAssetPath(texture));
            CommonEditorUtil.SaveTexture(output, dir, texture.name + "_gray.png");
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/生成为灰度图", true)]
        public static bool ConvertToGrayTextureValidation() {
            Object obj = Selection.activeObject;
            return obj is Texture2D;
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/透明通道设置为最小值", false)]
        public static void SetAlphaTominimum() {
            Texture2D texture = Selection.activeObject as Texture2D;
            bool isReadable = CommonEditorUtil.SetReadable(texture, true);

            Texture2D output = new Texture2D(texture.width, texture.height);

            Color[] colors = texture.GetPixels();
            CommonEditorUtil.SetReadable(texture, isReadable);

            for (int i = 0; i < texture.width * texture.height; i++) {
                if (i % 32 == 0) {
                    EditorUtility.DisplayProgressBar("SetAlphaTominimum", $"{(i + 1)} / {(texture.width * texture.height)}", (float)(i + 1) / (texture.width * texture.height));
                }
                Color color = colors[i];
                if (color.a == 0) {
                    color.a = 1f / 255;
                }
                colors[i] = color;
            }
            output.SetPixels(colors);
            output.Apply();

            string dir = Path.GetDirectoryName(AssetDatabase.GetAssetPath(texture));
            CommonEditorUtil.SaveTexture(output, dir, texture.name + "_modify.png");

            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/透明通道设置为1/255", true)]
        public static bool SetAlphaTominimumValidation() {
            Object obj = Selection.activeObject;
            return obj is Texture2D;
        }


        [MenuItem(CommonEditorConst.AssetsMenu + "/导出Multiple精灵图片", false)]
        public static void ExportMultipleSprite() {
            Texture2D texture = Selection.activeObject as Texture2D;

            string path = AssetDatabase.GetAssetPath(texture);
            TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
            bool isReadable = importer.isReadable;
            importer.isReadable = true;
            importer.SaveAndReimport();

            Object[] objs = AssetDatabase.LoadAllAssetsAtPath(path);
            for (int i = 1; i < objs.Length; i++) {
                Sprite sprite = objs[i] as Sprite;
                EditorUtility.DisplayProgressBar("Exporting", sprite.name, (float)i / objs.Length);
                try {
                    CommonEditorUtil.SaveTexture(sprite);
                }
                catch (System.Exception e) {
                    Debug.LogException(e);
                    break;
                }
            }

            importer.isReadable = isReadable;
            importer.SaveAndReimport();

            EditorUtility.ClearProgressBar();
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/导出Multiple精灵图片", true)]
        public static bool ExportMultipleSpriteValidation() {
            Object obj = Selection.activeObject;
            if (obj is Texture2D) {
                string path = AssetDatabase.GetAssetPath(obj);
                TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
                return importer.textureType == TextureImporterType.Sprite && importer.spriteImportMode == SpriteImportMode.Multiple;
            }
            return false;
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/Sprite另存为图片")]
        public static void SaveSpriteAsFile() {
            for (int i = 0; i < Selection.objects.Length; i++)
            {
                var obj = Selection.objects[i];
                if (obj is not Sprite sprite)
                    continue;

                string assetPath = AssetDatabase.GetAssetPath(sprite);
                string dir = Path.GetDirectoryName(assetPath);
                string filePath = Path.Combine(dir, sprite.name + ".png");
                if (File.Exists(filePath)) {
                    File.Delete(filePath);
                }

                bool readable = CommonEditorUtil.SetReadable(sprite.texture, true);
                var colors = sprite.texture.GetPixels((int)sprite.rect.x, (int)sprite.rect.y, (int)sprite.rect.width, (int)sprite.rect.height);
                CommonEditorUtil.SetReadable(sprite.texture, readable);

                Texture2D texture = new Texture2D((int)sprite.rect.width, (int)sprite.rect.height);
                texture.SetPixels(colors);
                texture.Apply();

                CommonEditorUtil.SaveTexture(texture, filePath);
            }
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/Sprite另存为图片", true)]
        public static bool SaveSpriteAsFileValidation() {
            return Selection.objects.Where(x => x is Sprite).Any();
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/应用脚本模板", false)]
        public static void ApplyScriptTemplate() {
            string path = AssetDatabase.GetAssetPath(Selection.activeObject);

            string _namespace = "Jinndev";
            string _classname = Selection.activeObject.name;
            string _extends = "MonoBehaviour";

            StringBuilder builder = new StringBuilder();
            builder.AppendLine("using System.Collections;");
            builder.AppendLine("using System.Collections.Generic;");
            builder.AppendLine("using UnityEngine;");
            builder.AppendLine("using UnityEngine.UI;");
            builder.AppendLine("");
            builder.AppendLine($"namespace {_namespace} {{");
            builder.AppendLine("");
            builder.AppendLine($"    public class {_classname} : {_extends} {{");
            builder.AppendLine("");
            builder.AppendLine("");
            builder.AppendLine("");
            builder.AppendLine("    }");
            builder.AppendLine("");
            builder.AppendLine("}");

            string script = builder.ToString();

            File.WriteAllText(path, script);
            AssetDatabase.Refresh();
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/应用脚本模板", true)]
        public static bool ApplyScriptTemplateValidation() {
            return Selection.activeObject != null && Selection.activeObject is MonoScript;
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/合并文件夹内的图片", false)]
        public static void PackDirectoryImages() {
            // 读取图片
            string dir = AssetDatabase.GetAssetPath(Selection.activeObject);
            string[] files = Directory.GetFiles(dir, "*");
            List<string> images = new List<string>();
            foreach (string file in files) {
                if (CommonUtil.IsImageFile(file)) {
                    images.Add(file);
                }
            }

            // 计算大小
            Vector2Int maxSize = new Vector2Int(0, 0);
            List<Texture2D> textures = new List<Texture2D>();

            for (int i = 0; i < images.Count; i++) {
                EditorUtility.DisplayProgressBar("读取", $"{i + 1}/{images.Count}", (float)(i + 1) / images.Count);
                Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(images[i]);
                if (texture == null) {
                    continue;
                }
                maxSize.x = Mathf.Max(maxSize.x, texture.width);
                maxSize.y = Mathf.Max(maxSize.y, texture.height);
                textures.Add(texture);
            }

            int rows = Mathf.CeilToInt(Mathf.Sqrt(textures.Count));
            rows = Mathf.ClosestPowerOfTwo(rows);
            int columns = Mathf.CeilToInt((float)images.Count / rows);
            columns = Mathf.NextPowerOfTwo(columns);

            int width = maxSize.x * columns;
            int height = maxSize.y * rows;
            Texture2D output = new Texture2D(width, height);
            output.SetPixels(0, 0, width, height, new Color[width * height]);

            // 开始生成
            int column = 0;
            int row = rows - 1;
            for (int i = 0; i < textures.Count; i++) {
                int x = column * maxSize.x;
                int y = row * maxSize.y;

                EditorUtility.DisplayProgressBar("生成", $"{i + 1}/{textures.Count}", (float)(i + 1) / textures.Count);
                column++;
                if (column == columns) {
                    column = 0;
                    row--;
                }

                bool readable = CommonEditorUtil.SetReadable(textures[i], true);
                Color[] colors = textures[i].GetPixels();
                CommonEditorUtil.SetReadable(textures[i], readable);
                output.SetPixels(x, y, maxSize.x, maxSize.y, colors);
            }
            EditorUtility.ClearProgressBar();

            // 写入文件
            output.Apply();
            byte[] bytes = output.EncodeToPNG();
            DestroyImmediate(output);

            string outputFile = dir + $"_{rows}x{columns}_{textures.Count}.png";
            File.WriteAllBytes(outputFile, bytes);

            AssetDatabase.Refresh();

            TextureImporter importer = AssetImporter.GetAtPath(outputFile) as TextureImporter;
            if (importer != null) {
                importer.mipmapEnabled = false;
                importer.alphaIsTransparency = true;
                importer.filterMode = FilterMode.Point;
                importer.SaveAndReimport();
            }
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/合并文件夹内的图片", true)]
        public static bool PackDirectoryImagesValidation() {
            return Selection.activeObject != null && Selection.activeObject is DefaultAsset;
        }

        /*
        [MenuItem(CommonEditorConst.AssetsMenu + "/动画删减帧", false)]
        public static void ReduceAnimationScaleKey() {
            try {
                var objs = Selection.objects;
                for (int i = 0; i < objs.Length; i++) {
                    EditorUtility.DisplayProgressBar("CompressAnim", objs[i].name + " Compressing...", ((float)i / objs.Length));
                    if (objs[i] is AnimationClip) {
                        CommonEditorUtil.ReduceScaleKey(objs[i] as AnimationClip, "localscale");
                    }
                }
            }
            catch (System.Exception) {
                EditorUtility.ClearProgressBar();
                throw;
            }
            EditorUtility.ClearProgressBar();
        }

        [MenuItem(CommonEditorConst.AssetsMenu + "/动画精度压缩", false)]
        public static void ReduceAnimationFloatPrecision() {
            try {
                var objs = Selection.objects;
                for (int i = 0; i < objs.Length; i++) {
                    EditorUtility.DisplayProgressBar("CompressAnim", objs[i].name + " Compressing...", ((float)i / objs.Length));
                    if (objs[i] is AnimationClip) {
                        CommonEditorUtil.ReduceFloatPrecision(objs[i] as AnimationClip);
                    }
                }
            }
            catch (System.Exception) {
                EditorUtility.ClearProgressBar();
                throw;
            }
            EditorUtility.ClearProgressBar();
        }
        */

    }

}
